import mysql from "mysql";
import DB from "./DB"

/** 事务类 */
export default class Trans {

    /** 事物对象池 */
    private static _pool: Trans[] = []

    /** 连接池中的连接 */
    private _conn: mysql.PoolConnection
    private constructor() { }

    /** 连接池连接 */
    get conn() {
        this._conn.statistics
        return this._conn;
    }

    /** 从对象池中分配一个事物 */
    static async alloc() {
        let ins = Trans._pool.pop() || new Trans()
        ins._conn = await DB.getConn();
        return ins
    }

    /** 从对象池中分配一个事物并开始 */
    static async begin() {
        let ins = await Trans.alloc()
        return await ins.begin()
    }

    /** 开始事务 */
    begin() {
        return new Promise<Trans>(async (res, rej) => {
            try {
                this.conn.beginTransaction((err) => {
                    if (err) {
                        this.conn.release();
                        rej(err)
                    } else {
                        res(this)
                    }
                })
            } catch (err) {
                rej(err);
            }
        })
    }

    /** 完成事物 */
    commit() {
        return new Promise<void>(async (res, rej) => {
            this.conn.commit(err => err ? rej(err) : res());
        })
    }

    /** 释放事物 */
    release() {
        this.conn.release();
    }

    /** 完成并释放事物 */
    async commitRelease() {
        await this.commit();
        this.release();
    }

    /** 回滚 */
    rollback() {
        return new Promise<void>((res, rej) => {
            this.conn.rollback(err => err ? rej(err) : res());
        })
    }

    /** 执行sql语句 */
    execute(sql: string, values?: any[]) {
        return DB.execute(sql, values, this.conn)
    }

    /** 联合语句 */
    union(sqlArr: { sql: string, val: any[] }[]) {
        return DB.union(sqlArr, this.conn);
    }

    /** 计数 */
    count(cfg: DB.ICountCfg) {
        return DB.count(cfg, this.conn)
    }

    /** 查询 */
    query(cfg: DB.IQueryCfg) {
        return DB.query(cfg, this.conn)
    }

    /** 返回查询sql语句 */
    query2sql(cfg: DB.IQueryCfg) {
        return DB.query2sql(cfg)
    }

    /** 查询一个 */
    queryOne(cfg: DB.IQueryCfg) {
        return DB.queryOne(cfg, this.conn)
    }

    /** 插入 */
    insert(cfg: DB.IInsertCfg) {
        return DB.insert(cfg, this.conn)
    }

    /** 修改 */
    update(cfg: DB.IUpdateCfg) {
        return DB.update(cfg, this.conn)
    }

    /** 删除 */
    del(cfg: DB.IDelCfg) {
        return DB.del(cfg, this.conn)
    }
}